package com.littlerpc.proxy.proxy;


import com.littlerpc.protocol.net.annotation.RpcProxy;
import com.littlerpc.protocol.net.common.RpcClient;
import com.littlerpc.protocol.net.common.RpcRequest;
import com.littlerpc.proxy.util.ProxyUtil;
import lombok.Setter;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

import java.lang.reflect.*;
import java.util.Set;

/**
 *
 * @author ChengPeng
 * @date 2017/7/2
 * 用于将RpcProxy.class注解的类，注入代理对象，在controller中，通过autotwrite注解获取
 * 这个类用于在spring启动是扫描到的RpcProxy.class的注解类，进行注册到spring中
 */
public class RpcBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Setter
    private String [] scanPackages;
    @Setter
    private  RemoteClientInfo remoteClientInfo;

    private RpcClient client = null;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        //获取所有RpcProxy注解类
        Set<Class<?>> classesWithAnnotationClass = ProxyUtil.getClassesWithAnnotationClass(RpcProxy.class,scanPackages );

        try {
            client = RpcClientPoolUtil.rpcClient(remoteClientInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }

        classesWithAnnotationClass.forEach(cla -> {
            Object info = getInfo(cla);
            //获取RpcProxy注册的value的值
            String beanName = cla.getAnnotation(RpcProxy.class).value();
            //进行注册
            beanFactory.registerSingleton(beanName,info);
        });
        System.out.println("***************************************"+beanFactory.getBeanDefinitionNames());



    }

    private Object getInfo(Class<?> cla){
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{cla}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                if (Object.class == method.getDeclaringClass()) {
                    String name = method.getName();
                    if ("equals".equals(name)) {
                        return proxy == args[0];
                    } else if ("hashCode".equals(name)) {
                        return System.identityHashCode(proxy);
                    } else if ("toString".equals(name)) {
                        return proxy.getClass().getName() + "@" +
                                Integer.toHexString(System.identityHashCode(proxy)) +
                                ", with InvocationHandler " + this;
                    } else {
                        throw new IllegalStateException(String.valueOf(method));
                    }
                }
                

                System.out.println("netty******************************************"+client);

                //构建请求对象
                RpcRequest request =  RpcRequest.buildRequest(cla,method, args);
                //将请求对象通过RpcClient发送到服务提供端
                Object send = client.send(request);
                return send;
            }
        });

    }


}
